#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    menuTable=TD_MENU;
    statementTable=REF_STATEMENT;

    defaultWinTitle=QString("%1 - %2").arg(DEF_TITLE).arg(SP_VER);
    setWindowTitle(defaultWinTitle);

    queryWidget=nullptr;
    entityEditor=nullptr;
    logViewer=new LogViewer(this);
    connect(this,&MainWindow::appendLog,
            logViewer,&LogViewer::appendLog);

    startUp();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::criticalToQuit(const QString &title, const QString &message)
{
    // 如果事件循环没有运行，则QCoreApplication::Exit()不会执行任何操作，在这种情况下，应该调用exit(EXIT_FAILURE)
    auto result=QMessageBox::critical(this,title,message,QMessageBox::Ok,QMessageBox::Ok);
    if(result == QMessageBox::Ok)
    {
        exit(EXIT_FAILURE);
    }
}

void MainWindow::startUp()
{
    if(!initializeMySQL())
    {
        criticalToQuit("致命错误","无法连接到Preset数据库，程序现在退出");
    }

    if(!initializeDB_201())
    {
        criticalToQuit("致命错误","无法连接到U8_201数据库，程序现在退出");
    }

    if(!initializeDB_206())
    {
        criticalToQuit("致命错误","无法连接到U8_206数据库，程序现在退出");
    }

    if(db_preset.isOpen())
    {
        updateQueryMenu();
    }

    setQueryWidget();
    move(100,100);
}

void MainWindow::setQueryWidget()
{
    if(queryWidget == nullptr)
    {
        queryWidget=new QueryWidget(this);
        connect(queryWidget,&QueryWidget::showMessage,
                this,&MainWindow::showMessage);
        connect(queryWidget,&QueryWidget::transferLog,
                logViewer,&LogViewer::appendLog);
    }
    setCentralWidget(queryWidget);
}

void MainWindow::updateQueryMenu()
{
    if(!ui->menuQuery->isEmpty())
    {
        ui->menuQuery->disconnect();
        ui->menuQuery->clear();
    }

    if(!queryMenuCache.isEmpty())
        queryMenuCache.clear();

    QSqlQuery query(db_preset);
    QString sql=QString("select label,detail from %1 where category='%2' order by seq")
            .arg(menuTable)
            .arg("Query");
    appendLog(QString("[%1]%2")
              .arg("Query").arg(sql));

    query.exec(sql);
    while (query.next()) {
        auto label=query.value(0).toString();
        if(label.isEmpty())
            continue;

        if(label == "#")
        {
            ui->menuQuery->addSeparator();
            continue;
        }

        auto detail=query.value(1).toString();
        ui->menuQuery->addAction(label);
        queryMenuCache.insert(label,detail);
    }

    if(!queryMenuCache.isEmpty())
        connect(ui->menuQuery,&QMenu::triggered,
                this,&MainWindow::processQueryMenu);
}

QMap<QString,QString> MainWindow::fetchStatement(const QString &entry)
{
    QMap<QString,QString> map;
    QSqlQuery query(db_preset);
    QString sql=QString("select label,detail from %1 where entry='%2'")
            .arg(statementTable)
            .arg(entry);
    appendLog(QString("[%1] %2")
              .arg("Statement").arg(sql));

    query.exec(sql);
    while (query.next()) {
        auto label=query.value(0).toString();
        auto detail=query.value(1).toString();
        map.insert(label,detail);
    }
    return map;
}

void MainWindow::extendStatement(QMap<QString, QString> &map)
{
    QSqlQuery query(db_preset);
    QString sql=QString("select label,detail from %1 where entry='%2'")
            .arg(statementTable)
            .arg("Common");
    appendLog(QString("[%1] %2")
              .arg("ExtendStatement").arg(sql));

    query.exec(sql);
    while (query.next()) {
        auto label=query.value(0).toString();
        auto detail=query.value(1).toString();
        map.insert(label,detail);
    }
}

void MainWindow::processQueryMenu(QAction *action)
{
    auto label=action->text();
    if(queryMenuCache.contains(label))
    {
        setWindowTitle(defaultWinTitle + " - " + label);
        auto entry=queryMenuCache.value(label);
        if(label.contains("<206>"))
            prepareQueryWidget(entry,U8_CONNECTION_206);
        else
            prepareQueryWidget(entry,U8_CONNECTION_201);
    }
}

void MainWindow::prepareQueryWidget(const QString &entry, const QString &connectionName)
{
    queryWidget->setConnection(connectionName);

    auto statements=fetchStatement(entry);
    if(statements.isEmpty())
    {
        showMessage("功能缺失，可能正在开发中，也可能不提供该功能[QueryWidget]");
        return;
    }

    statements.insert("entry",entry);
    extendStatement(statements);
    queryWidget->prepareStatement(statements);

    resize(DEF_WIDTH,DEF_HEIGHT);
}

void MainWindow::showMessage(const QString &message)
{
    ui->statusbar->showMessage(message,6000);
}

bool MainWindow::initializeMySQL()
{
    db_preset = getConnectionFromSHM(SHM_KEY,ENTRY_U8,MYSQL_CONNECTION);
    if(!db_preset.isValid())
        return false;

    if(db_preset.open())
        return true;
    else
    {
        qDebug() << db_preset.lastError().text();
        return false;
    }
}

bool MainWindow::initializeDB_201()
{
    db_201 = odbc_getConnectionFromSHM(SHM_KEY,ENTRY_U8_201,U8_CONNECTION_201);
    if(!db_201.isValid())
        return false;

    if(db_201.open())
        return true;
    else
    {
        qDebug() << db_201.lastError().text();
        return false;
    }
}

bool MainWindow::initializeDB_206()
{
    db_206 = odbc_getConnectionFromSHM(SHM_KEY,ENTRY_U8_206,U8_CONNECTION_206);
    if(!db_206.isValid())
        return false;

    if(db_206.open())
        return true;
    else
    {
        qDebug() << db_206.lastError().text();
        return false;
    }
}

void MainWindow::on_actionLogViewer_triggered()
{
    if(logViewer->isHidden())
        logViewer->show();
}

void MainWindow::on_actionEntityEditor_triggered()
{
    if(entityEditor == nullptr)
        entityEditor=new EntityEditor(this,db_preset);
    entityEditor->show();
}
